package com.zlsf.publish.local;


import com.zlsf.codec.MP3Encoder;
import com.zlsf.flv.AudioTag;
import com.zlsf.flv.FlvAudioTagEncoder;
import com.zlsf.flv.FlvEncoder;
import com.zlsf.util.ByteBufUtils;
import com.zlsf.util.FLVUtils;
import com.zlsf.util.HttpChunk;
import io.netty.buffer.ByteBuf;
import io.vertx.ext.web.RoutingContext;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class VideoSubscriberLocal extends SubscriberLocal {
  private long videoTimestamp = 0;
  private long audioTimestamp = 0;
  private long lastVideoFrameTimeOffset = 0;
  private long lastAudioFrameTimeOffset = 0;
  private boolean videoHeaderSent = false;

  public VideoSubscriberLocal(String tag, RoutingContext ctx) {
    super(tag, ctx);
  }

  @Override
  public void onVideoData(long timeoffset, byte[] data, FlvEncoder flvEncoder) {
    if (lastVideoFrameTimeOffset == 0) lastVideoFrameTimeOffset = timeoffset;
    // 之前是不是已经发送过了？没有的话，需要补发FLV HEADER的。。。
    if (videoHeaderSent == false && flvEncoder.videoReady()) {
      enqueue(HttpChunk.make(flvEncoder.getHeader().getBytes()));
      enqueue(HttpChunk.make(flvEncoder.getVideoHeader().getBytes()));

      // 直接下发第一个I帧
      byte[] iFrame = flvEncoder.getLastIFrame();
      if (iFrame != null) {
        FLVUtils.resetTimestamp(iFrame, (int) videoTimestamp);
        byte[] datas = HttpChunk.make(data);
        enqueue(datas);
      }
      videoHeaderSent = true;
    }
    if (data == null) return;
    // 修改时间戳
    // System.out.println("Time: " + videoTimestamp + ", current: " + timeoffset);
    FLVUtils.resetTimestamp(data, (int) videoTimestamp);
    videoTimestamp += (int) (timeoffset - lastVideoFrameTimeOffset);
    lastVideoFrameTimeOffset = timeoffset;

    enqueue(HttpChunk.make(data));

  }

  private FlvAudioTagEncoder audioEncoder = new FlvAudioTagEncoder();
  MP3Encoder mp3Encoder = new MP3Encoder();

  @Override
  public void onAudioData(long timeoffset, byte[] data, FlvEncoder flvEncoder) {
    if (!videoHeaderSent) return;

    byte[] mp3Data = mp3Encoder.encode(data);
    if (mp3Data == null || mp3Data.length == 0) return;
    AudioTag audioTag = new AudioTag(0, mp3Data.length + 1, AudioTag.MP3, (byte) 0, (byte) 1, (byte) 0, mp3Data);
    byte[] frameData = null;
    try {
      ByteBuf audioBuf = audioEncoder.encode(audioTag);
      frameData = ByteBufUtils.readReadableBytes(audioBuf);
    } catch (Exception e) {
      e.printStackTrace();
    }

    if (lastAudioFrameTimeOffset == 0) lastAudioFrameTimeOffset = timeoffset;

    if (data == null) return;

    FLVUtils.resetTimestamp(frameData, (int) audioTimestamp);
    audioTimestamp += (int) (timeoffset - lastAudioFrameTimeOffset);
    lastAudioFrameTimeOffset = timeoffset;

    enqueue(HttpChunk.make(frameData));
  }

  @Override
  public void close() {
    super.close();
    mp3Encoder.close();
  }
}
